package cn.amaake.magicplugin.satoken.autoconfigure;

import cn.amaake.magicplugin.satoken.Interceptor.CustomAuthorizationInterceptor;
import cn.amaake.magicplugin.satoken.Interceptor.CustomRequestInterceptor;
import cn.amaake.magicplugin.satoken.config.MagicApiSaTokenConfig;
import cn.amaake.magicplugin.satoken.config.SaTokenMode;
import cn.amaake.magicplugin.satoken.filter.TokenResponseHeaderFilter;
import cn.amaake.magicplugin.satoken.interfaces.SatokenAbstract;
import cn.amaake.magicplugin.satoken.interfaces.StpInterfaceImpl;
import cn.amaake.magicplugin.satoken.model.SatokenUser;
import cn.amaake.magicplugin.satoken.template.SaOAuth2TemplateImpl;
import cn.amaake.magicplugin.satoken.web.SaOAuth2ServerController;
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.json.JSONUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.ssssssss.magicapi.core.config.MagicAPIProperties;
import org.ssssssss.magicapi.core.config.MagicConfiguration;
import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
import org.ssssssss.magicapi.core.model.JsonBean;
import org.ssssssss.magicapi.core.model.Plugin;
import org.ssssssss.magicapi.core.web.MagicControllerRegister;
import org.ssssssss.magicapi.utils.Mapping;

@Configuration
@EnableConfigurationProperties(MagicApiSaTokenConfig.class)
public class MagicAPISaTokenConfiguration implements MagicPluginConfiguration {

    private final MagicAPIProperties properties;
    private final ApplicationContext applicationContext;
    private final MagicApiSaTokenConfig magicApiSaTokenConfig;


    public MagicAPISaTokenConfiguration(MagicAPIProperties properties, MagicApiSaTokenConfig magicApiSaTokenConfig, ApplicationContext applicationContext){
        this.properties = properties;
        this.magicApiSaTokenConfig = magicApiSaTokenConfig;
        this.applicationContext = applicationContext;
    }

//    @Bean
//    public SatokenAbstract satokenAbstract() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
//
//        return applicationContext.getBean(SatokenAbstract.class);
////        // 实现类路径
////        String classPath = "src.main.java.cn.amaake.magicplugin.satoken.interfaces.SatokenAbstract";
////        // 获取实现类Class
////        Class<? extends SatokenAbstract> otClass = (Class<? extends SatokenAbstract>) Class.forName(classPath);
////        // 获取有参构造
////        Constructor<? extends SatokenAbstract> constructor = otClass.getConstructor(MagicApiSaTokenConfig.class);
////        // 获取实例,用抽象类接收
////        return constructor.newInstance(magicApiSaTokenConfig);
//    }

    @Bean
    public TokenResponseHeaderFilter tokenResponseHeaderFilter(){
        return new TokenResponseHeaderFilter(magicApiSaTokenConfig);
    }


//    @Bean
//    public SaTokenConfig getSaTokenConfigPrimary() {
//        return magicApiSaTokenConfig.getSaToken();
//    }


    @Bean
    public CustomAuthorizationInterceptor customAuthorizationInterceptor(ApplicationContext applicationContext){
        return new CustomAuthorizationInterceptor(magicApiSaTokenConfig,applicationContext);
    }

    @Bean
    public CustomRequestInterceptor customRequestInterceptor(ApplicationContext applicationContext){
        return new CustomRequestInterceptor(magicApiSaTokenConfig,applicationContext);
    }

    @Bean
    public StpInterfaceImpl stpInterface(ApplicationContext applicationContext){
        return new StpInterfaceImpl(applicationContext);
    }

    @Bean
    @Primary
    @ConditionalOnProperty(prefix = "magic-api.satoken",name = "satokenmode",havingValue = "OAUTH2SERVER")
    public SaOAuth2Config getOAuth2ConfigPrimary() {
        return magicApiSaTokenConfig.getOauth2();
    }


    @Bean
    @ConditionalOnProperty(prefix = "magic-api.satoken",name = "satokenmode",havingValue = "OAUTH2SERVER")
    public SaOAuth2TemplateImpl saOAuth2TemplateImpl(SatokenAbstract satokenAbstract){
        return new SaOAuth2TemplateImpl(satokenAbstract);
    }

    /**
     *   注册Controller，如果有的话
     */
    @Override
    public MagicControllerRegister controllerRegister() {
        return new MagicControllerRegister() {
            @Override
            public void register(Mapping mapping, MagicConfiguration magicConfiguration) {
                if(magicApiSaTokenConfig.getSatokenmode()==SaTokenMode.OAUTH2SERVER){
                    mapping.registerController(new SaOAuth2ServerController(magicConfiguration));
                }
            }
        };
    }

    @Bean
    @ConditionalOnProperty(prefix = "magic-api.satoken",name = "satokenmode",havingValue = "OAUTH2SERVER")
    public void setSaOAuth2Config(SaOAuth2Config cfg) {
        cfg.
            // 配置：未登录时返回的View
            setNotLoginView(() -> {
                return new JsonBean<>(1,"当前会话在OAuth-Server端尚未登录", JSONUtil.createObj().put("url","/oauth2/doLogin"));
            }).
            // 配置：登录处理函数
            setDoLoginHandle((name, pwd) -> {

                SatokenAbstract satokenAbstract = applicationContext.getBean(SatokenAbstract.class);
                SatokenUser satokenUser = satokenAbstract.getSatokenUser(name,pwd,null,false);

                if(satokenUser == null){
                    String id = satokenUser.getId();
                    StpUtil.login(id);
                    return new JsonBean<>(1,"登陆成功");
                }
                return new JsonBean<>(0,"账号名或密码错误");
            }).
            // 配置：确认授权时返回的View
            setConfirmView((clientId, scope) -> {
                return new JsonBean<>(1,"应用 " + clientId + " 请求授权：" + scope, JSONUtil.createObj().put("url","/oauth2/doConfirm?client_id=" + clientId + "&scope=" + scope));
            })
        ;
    }

    @Override
    public Plugin plugin() {
        return new Plugin("SaToken鉴权插件");
    }
}
